package dcc.shannonfano;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

/**
 * The Class BitWriter. File Bit Writer - Write to Files BitWise
 */
public class BitWriter {

	/** The file name. */
	private String fileName;

	/** The output file. */
	private File outputFile;
	
	/** The fout. */
	private FileOutputStream fout;
	
	/** The outf. */
	private BufferedOutputStream outf;
	
	/** The current byte. */
	private String currentByte;

	/**
	 * Instantiates a new bit writer.
	 *
	 * @throws Exception the exception
	 */
	public BitWriter() throws Exception {
		try {
			fileName = "";
			// loadFile(fileName);
		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * Instantiates a new bit writer.
	 *
	 * @param txt the txt
	 * @throws Exception the exception
	 */
	public BitWriter(String txt) throws Exception {
		try {
			fileName = txt;
			loadFile(fileName);
		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * Load file.
	 *
	 * @param txt the txt
	 * @return true, if successful
	 * @throws Exception the exception
	 */
	public boolean loadFile(String txt) throws Exception {
		fileName = txt;

		try {
			outputFile = new File(fileName);
			fout = new FileOutputStream(outputFile);
			outf = new BufferedOutputStream(fout);

			currentByte = "";
			return true;

		} catch (Exception e) {
			throw e;
		}

		// return true;
	}

	/**
	 * Put bit.
	 *
	 * @param bit the bit
	 * @throws Exception the exception
	 */
	public void putBit(int bit) throws Exception {

		try {
			bit = bit % 2;
			currentByte = currentByte + Integer.toString(bit);

			if (currentByte.length() >= 8) {

				int byteval = Integer.parseInt(currentByte.substring(0, 8), 2);
				outf.write(byteval);
				currentByte = ""; // reset
			}

		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * Put bits.
	 *
	 * @param bits the bits
	 * @throws Exception the exception
	 */
	public void putBits(String bits) throws Exception {

		try {
			while (bits.length() > 0) {
				int bit = Integer.parseInt(bits.substring(0, 1));
				putBit(bit);
				bits = bits.substring(1);
			}
		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * Put string.
	 *
	 * @param txt the txt
	 * @throws Exception the exception
	 */
	public void putString(String txt) throws Exception {

		try {
			while (txt.length() > 0) {
				String binstring = Integer.toString(txt.charAt(0), 2);
				binstring = leftPad8(binstring);

				putBits(binstring);
				txt = txt.substring(1);
			}
		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * Left pad8.
	 *
	 * @param txt the txt
	 * @return the string
	 */
	String leftPad8(String txt) {
		while (txt.length() < 8)
			txt = "0" + txt;
		return txt;
	}

	/**
	 * Right pad8.
	 *
	 * @param txt the txt
	 * @return the string
	 */
	String rightPad8(String txt) {
		while (txt.length() < 8)
			txt += "0";
		return txt;
	}

	/**
	 * Close file.
	 *
	 * @throws Exception the exception
	 */
	public void closeFile() throws Exception {

		try {

			// check if incomplete byte exists
			while (currentByte.length() > 0) {
				putBit(1);
			}
			outf.close();

		} catch (Exception e) {
			throw e;
		}
	}

}
